﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Security.Cryptography;
using System.IO;

namespace Heroius.Stample
{
    /// <summary>
    /// 对称加密经理
    /// <para>采用DES对称算法，并基于时间密钥对字符串加密或解密</para>
    /// </summary>
    public class SymManager
    {
        /// <summary>
        /// 实例化对称加密经理
        /// </summary>
        /// <param name="iv">初始向量，长度为8的byte数组</param>
        /// <param name="encoding">指定编码，默认为UTF8</param>
        public SymManager(byte[] iv, Encoding encoding = null)
        {
            core = new DESCryptoServiceProvider(); // 仅支持DES，这与时间格式有关
            core.IV = iv;
            if (encoding == null)
            {
                Encoding = Encoding.UTF8;
            }
            else
            {
                Encoding = encoding;
            }
        }
        SymmetricAlgorithm core;

        /// <summary>
        /// 获取或设置初始向量
        /// </summary>
        internal byte[] IV { get; set; }
        /// <summary>
        /// 获取或设置编码
        /// </summary>
        internal Encoding Encoding { get; set; }

        /// <summary>
        /// 生成基于时间的密钥
        /// <para>时间采样精确到小时</para>
        /// <para>以2018年2月18日15:49为例，密钥为 18021815。</para>
        /// </summary>
        /// <returns></returns>
        public byte[] GenKey()
        {
            return Encoding.UTF8.GetBytes(DateTime.Now.ToString("YYYYMMDDHH").Substring(2)); //DES 要求 8 字节的key
        }

        /// <summary>
        /// 加密明文
        /// </summary>
        /// <param name="code">明文</param>
        /// <param name="key">密钥，若不设置则基于时间自动生成</param>
        /// <returns></returns>
        public string Encrypt(string code, byte[] key = null)
        {
            if (key == null)
            {
                core.Key = GenKey();
            }
            else
            {
                core.Key = key;
            }

            var decripted = Encoding.GetBytes(code);
            MemoryStream ms = new MemoryStream();
            var enc = new CryptoStream(ms, core.CreateEncryptor(), CryptoStreamMode.Write);
            enc.Write(decripted, 0, decripted.Length);
            enc.FlushFinalBlock();
            var result = Encoding.GetString(ms.ToArray());
            ms.Close();
            enc.Close();
            return result;
        }
        /// <summary>
        /// 解密暗文
        /// </summary>
        /// <param name="code">暗文</param>
        /// <param name="key">密钥，若不设置则基于时间自动生成</param>
        /// <returns></returns>
        public string Decrypt(string code, byte[] key = null)
        {
            if (key == null)
            {
                core.Key = GenKey();
            }
            else
            {
                core.Key = key;
            }

            var encrypted = Encoding.GetBytes(code);
            MemoryStream ms = new MemoryStream();
            var dec = new CryptoStream(ms, core.CreateDecryptor(), CryptoStreamMode.Write);
            dec.Write(encrypted, 0, encrypted.Length);
            dec.FlushFinalBlock();
            var result = Encoding.GetString(ms.ToArray());
            ms.Close();
            dec.Close();
            return result;
        }
    }
}
